package com.spudtech.utils
{
    
    import flash.geom.*;
    import flash.display.*;
    
    import flash.utils.*;
    
    import com.spudtech.error.*;
    import com.spudtech.graphics.*;
    import com.spudtech.collision.*;
    
    
    public class SpudResourceManager
    {
        
        // The list of resource objects, listed by ID
        protected var _resourceList : Dictionary;
        
        // Pattern for resource with 'null' ID's
        // that should be returned as 'null'
        protected var _nullPattern : RegExp;
        
        // Resource manager singleton
        protected static var _resourceMgr : SpudResourceManager;
        
        public function SpudResourceManager()
        {
            _resourceList = new Dictionary();
            
            
            // nullPattern matches strings that
            // end with the following:
            //   - .null
            //   - .empty
            //   - null
            //
            // It is not case-sensitive
            //
            var null_pattern_str : String = "";
            
            null_pattern_str += "(none|";       // 'none' or..
            null_pattern_str += "(\\.";         // dot then...
            null_pattern_str += "(null|empty)"; // 'null' or 'empty' then...
            null_pattern_str += "))$";          // Closing parens then end-of-string
            
            _nullPattern = new RegExp(null_pattern_str,"i");
            
        }
        
        public static function init() : void
        {
            // Implement in derived classes
            
        }
        
        
        public static function get resourceMgr() : SpudResourceManager
        {
            return _resourceMgr;
        }
        
        
        public function get resourceList() : Dictionary
        {
            return _resourceList;
        }
        
        public function get nullPattern() : RegExp
        {
            return _nullPattern;
        }
        
        
        public function getResource(id : *) : Object
        {
            if (String(id).match(nullPattern).length > 0)
            {
                // There is at least one match
                // for the null pattern
                
                return null;
                
            }
            
            if (resourceList[id] == null)
            {
                throw new SpudResourceNotFoundError("Resource not found",SpudResourceNotFoundError.CLASS_NOT_FOUND);
                
                return null;
                
            }
            else
            {
                return resourceList[id];
            }
            
        }
        
        public function getImageFile(id : *) : DisplayObject
        {
            var raw_resource : Object = getResource(id);
            
            if (raw_resource is Class)
            {
                // The resource is a class,
                // so we instantiate it
                var obj_resource : Object = new raw_resource();
                
                if (obj_resource is Bitmap)
                {
                    return Bitmap(obj_resource);
                }
                else
                {
                    // It's not an image
                    throw new SpudDataFormatError("Resource is not a subclass of an image file",SpudDataFormatError.WRONG_CLASS_TYPE);
                    
                    return null;
                    
                }
                
            }
            else if (raw_resource is Bitmap)
            {
                return Bitmap(raw_resource);
            }
            else
            {
                throw new SpudDataFormatError("Resource is not an image file",SpudDataFormatError.WRONG_CLASS_TYPE);
                
                return null;
                
            }
            
        }
        
        public function getXMLFile(id : *) : XML
        {
            var raw_resource : Object = getResource(id);
            
            if (raw_resource is Class)
            {
                var obj_resource : Object = new raw_resource();
                
                if (obj_resource is XML)
                {
                    // Hot damn!
                    // It's already an XML object!
                    // Let's just return it!
                    
                    return XML(obj_resource);
                    
                }
                else if (obj_resource is ByteArray)
                {
                    var byte_arr_resource : ByteArray
                    
                    var str_resource : String;
                    
                    var xml_resource : XML;
                    
                    byte_arr_resource = ByteArray(obj_resource);
                    
                    str_resource = byte_arr_resource.readUTFBytes(byte_arr_resource.length);
                    
                    try
                    {
                        xml_resource = XML(str_resource);
                        
                        return xml_resource;
                        
                    }
                    catch (ex : TypeError)
                    {
                        if (ex.message.match(/.[Mm]alformed.+/).length > 0)
                        {
                            // The word 'malformed' shows up
                            // at least once in the message
                            // When an XML string has broken
                            // syntax, the XML() function
                            // throws a TypeError saying
                            // that an expression is
                            // 'malformed' so we know that
                            // if that shows up in the
                            // error message that the XML
                            // file had broken syntax
                            
                            throw new SpudDataFormatError("Resource is a bad XML file",SpudDataFormatError.BROKEN_XML_FILE);
                            
                            return null;
                            
                        }
                        else
                        {
                            // Otherwise, we just rethrow it
                            throw ex;
                            
                            return null;
                            
                        }
                        
                    }
                    
                }
                else
                {
                    try
                    {
                        xml_resource = XML(obj_resource);
                        
                        return xml_resource;
                        
                    }
                    catch (ex : TypeError)
                    {
                        if (ex.message.match(/.[Mm]alformed.+/).length > 0)
                        {
                            // The word 'malformed' occurs at
                            // least once, which means that
                            // the XML file had broken syntax
                            // See the block
                            // 'obj_resource is ByteArray'
                            // for how we know that
                            
                            throw new SpudDataFormatError("Resource is an invalid XML string",SpudDataFormatError.BROKEN_XML_FILE);
                            
                        }
                        else
                        {
                            throw new TypeError("Cannot convert resource into XML",ex.errorID);
                        }
                        
                    }
                }
                
                
            }
            else if (raw_resource is XML)
            {
                // Hot damn!
                // It's already an XML object!
                // Let's just return it!
                
                return XML(raw_resource);
                
            }
            else if (raw_resource is ByteArray)
            {
                
                byte_arr_resource = ByteArray(raw_resource);
                
                str_resource = byte_arr_resource.readUTFBytes(byte_arr_resource.length);
                
                try
                {
                    xml_resource = XML(str_resource);
                    
                    return xml_resource;
                    
                }
                catch (ex : TypeError)
                {
                    if (ex.message.match(/.[Mm]alformed.+/).length > 0)
                    {
                        // The word 'malformed' shows up
                        // at least once in the message
                        // When an XML string has broken
                        // syntax, the XML() function
                        // throws a TypeError saying
                        // that an expression is
                        // 'malformed' so we know that
                        // if that shows up in the
                        // error message that the XML
                        // file had broken syntax
                        
                        throw new SpudDataFormatError("Resource is a bad XML file",SpudDataFormatError.BROKEN_XML_FILE);
                        
                        return null;
                        
                    }
                    else
                    {
                        // Otherwise, we just rethrow it
                        throw ex;
                        
                        return null;
                        
                    }
                    
                }
                
            }
            else
            {
                try
                {
                    xml_resource = XML(raw_resource);
                    
                    return xml_resource;
                    
                }
                catch (ex : TypeError)
                {
                    if (ex.message.match(/.[Mm]alformed.+/).length > 0)
                    {
                        // The word 'malformed' occurs at
                        // least once, which means that
                        // the XML file had broken syntax
                        // See the block
                        // 'raw_resource is ByteArray'
                        // for how we know that
                        
                        throw new SpudDataFormatError("Resource is an invalid XML string",SpudDataFormatError.BROKEN_XML_FILE);
                        
                        return null;
                        
                    }
                    else
                    {
                        throw new TypeError("Cannot convert resource into XML",ex.errorID);
                        
                        return null;
                        
                    }
                    
                }
            }
            
            return null;
            
        }
        
    }
    
}
